import { BaseComp } from '../../../common/component/comp';

import events from './events';
import { z, layouts } from './layout';
import { Candidate } from './lottery';
import { Seat } from './seat';

/**
 * 一个 SeatList 可以同时显示 15 个 seat
 * 
 * 在发弹幕加人时, 加的 seat 放在从上往下数第 13 个位置, 前面的 seat 依次往上移 1 格;
 * 抽人时, 所有 16 个 seat 都要用
 */
class SeatList extends BaseComp {
  spPara = null;

  /** 当转起来时才有效的参数 */
  speed = 0;
  maxSpeed = 0;
  /** 是相对于 this.root.lottery.candidates 的 index */
  currentIndex = 0;
  /** 偏移量, 转起来的时候每个 seat 的 Y 偏移原值多少, 一般是负的 */
  offsetY = 0;
  /** 是否在选人阶段, 也就是转盘慢下来的阶段 */
  slowDown = false;
  
  constructor(args) {
    super(args.parent);
    this.zrender = args.zrender;
    this.zr = args.zr;
    
    this.layout = layouts.seats;
    /** 每个 seat 之间的 y 坐标之差 */
    this.rowSpacing = this.layout.height / 15;
    this.maxSpeed = this.rowSpacing * 0.72;
    /** 在发弹幕加人时, 新加的 seat 默认放的纵坐标位置 */
    this.startY = this.rowSpacing * 12;
    this.x = this.layout.x;
    this.y = this.layout.y;

    /** @type {Seat[]} */
    this.seats = [];
    for (let i = 0; i < 16; i++) {
      let seat = new Seat({
        parent: this,
        zrender: this.zrender,
        zr: this.zr,
        yLimit: -this.rowSpacing
      });
      this.seats.push(seat);
      seat.hide();
    }

    /** @type {Seat[]} */
    this.showSeats = [];

    this.on(events.CANDIDATE_ADDED, this.onCandidateAdded.bind(this));
    this.on(events.PHASE_RESET, this.onReset.bind(this));
    this.on(events.PHASE_BEGIN, this.onBegin.bind(this));
    this.on(events.PHASE_READY, this.onReady.bind(this));
    this.on(events.PHASE_PICKING, this.onPicking.bind(this));
  }

  init() {
    const [x, y] = this.absolutePos();
    const { zr, zrender, layout } = this;
    const spPara = this.spPara = new zrender.Polygon({
      shape : {
        points: [
          [0, layout.height],
          [layout.width, y + layout.height],
          [layout.width + layout.offsetX, 0],
          [layout.offsetX, 0],
        ]
      },
      style: { fill: '#0004' },
      position: [x, y],
      z: z.seats.list,
    });
    zr.add(spPara);
  }

  /**
   * Seat 所在的位置不是在一条竖线上, 所以需要通过 y 来推导 x (相对) 的值
   */
  confirmSeatX(y) {
    return (1 - y / layouts.height) * this.layout.offsetX;
  }

  /**
   * @param {Candidate} candidate 
   */
  onCandidateAdded(_, candidate) {
    // assert 当前正在允许发弹幕加人
    let newSeat = this.seats.pop();
    if (newSeat == null) {
      newSeat = this.showSeats.splice(0, 1)[0];
      newSeat.hide();
    }
    newSeat.load(candidate);
    newSeat.come(this.confirmSeatX(this.startY), this.startY);
    newSeat.show();

    let baseY = this.rowSpacing * (12 - this.showSeats.length);
    for (let i = 0; i < this.showSeats.length; i++) {
      let seat = this.showSeats[i];
      let y = this.rowSpacing * i + baseY;
      seat.moveSlowly(this.confirmSeatX(y), y);
      if (y > this.startY) {
        debugger;
      }
    }
    this.showSeats.push(newSeat);
  }

  onSeatOutside(seat) {
    seat.hide();

    let index = this.showSeats.findIndex(s => s === seat);
    if (index != -1) {
      this.showSeats.splice(index, 1);
      this.seats.push(seat);
    }

    if (this.seats.length + this.showSeats.length != 16) {
      debugger;
      throw this;
    }
  }

  onReset() {
    this.showSeats.forEach(s => s.hide());

    this.seats.push(...this.showSeats);
    this.showSeats = [];
    this.speed = 0;
  }

  onBegin() {
    this.onReset();

    /** @type {Candidate[]} 保证其长度为 13 */
    const candidates = this.root.lottery.participants.concat();
    if (candidates.length < 13) {
      while (candidates.length < 13) {
        candidates.splice(0, 0, null);
      }
    } else if (candidates.length > 13) {
      candidates.splice(0, candidates.length - 13);
    }

    candidates.forEach((c, index) => {
      if (c == null) return;

      let y = this.rowSpacing * index;
      let newSeat = this.seats.pop();
      newSeat.y = y;
      newSeat.x = this.confirmSeatX(y);
      newSeat.load(c);
      newSeat.show();
      this.showSeats.push(newSeat);
    });
  }

  onReady() {
    this.speed = this.maxSpeed;
    this.currentIndex = 0;
    this.slowDown = false;
    this.offsetY = 0;
    this.showSeats.push(...this.seats);
    this.seats = [];
    if (this.showSeats.length != 16) {
      console.error('seat 数量不对');
      throw this;
    }

    /** @type {Candidate[]} */
    const candidates = this.root.lottery.candidates;
    let index = this.currentIndex;
    for (let i = 0; i < this.showSeats.length; i++) {
      let seat = this.showSeats[i];
      let y = this.rowSpacing * i;
      seat.x = this.confirmSeatX(y);
      seat.y = y;
      seat.load(candidates[index]);
      seat.show();
      index = (index + 1) % candidates.length;
    }
  }

  onPicking() {
    this.slowDown = true;
  }

  tick() {
    if (this.speed === 0) {
      return;
    }

    let waitingForNext = false;
    let stopped = false;

    if (this.slowDown) {
      if (this.speed > 0.2) {
        this.speed -= (this.speed > 1) ? Math.random() * 0.2 + 0.1 : 0.1;
      } else {
        this.speed = 0.2;
        waitingForNext = true;
      }
    }

    /** @type {Candidate[]} */
    const candidates = this.root.lottery.candidates;
    this.offsetY -= this.speed;
    while (this.offsetY <= -this.rowSpacing) {
      this.offsetY += this.rowSpacing;
      this.currentIndex = (this.currentIndex + 1) % candidates.length;
    }

    if (waitingForNext && this.offsetY > -0.25) {
      this.speed = 0;
      this.offsetY = 0;
      this.slowDown = false;
      stopped = true;
    }

    let index = this.currentIndex;
    for (let i = 0; i < this.showSeats.length; i++) {
      let seat = this.showSeats[i];
      let y = this.rowSpacing * i + this.offsetY;
      seat.x = this.confirmSeatX(y);
      seat.y = y;
      seat.load(candidates[index]);
      index = (index + 1) % candidates.length;
    }

    if (stopped) {
      let chosenIndex = this.currentIndex + 7;
      chosenIndex = chosenIndex >= candidates.length ? chosenIndex - candidates.length : chosenIndex;
      let chosen = candidates[chosenIndex];
      this.emit(events.PHASE_PICKED, { chosen });

      // seat
      this.showSeats[7].makePrimary();
    } else {
      // 我那个中间的指针到底指的是谁
      let center = this.rowSpacing * 7;
      let y7 = Math.abs(this.showSeats[7].y - center);
      let y8 = Math.abs(this.showSeats[8].y - center);
      let centerY = y7 > y8 ? 8 : 7;

      this.showSeats[centerY].makeSecond();
      // 它上面和下面的那位改回原样
      this.showSeats[centerY + 1].dropPrimary();
      this.showSeats[centerY - 1].dropPrimary();
    }
  }
}



export {
  SeatList
};
